{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# 本代码是：《动手学深度学习_PyTorch版》这本书上的例子代码\n",
    "书在D:\\download\\下"
   ],
   "id": "2017cf20de88d11"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "execution_count": 1,
   "source": "import torch",
   "id": "initial_id",
   "outputs": []
  },
  {
   "cell_type": "code",
   "id": "952ebcf3ad1f17d4",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-12-21T14:36:02.755723Z",
     "start_time": "2024-12-21T14:36:02.747633Z"
    }
   },
   "source": [
    "e1 = torch.empty(3,4) # empty：指的是未初始化的，即值是不确定的\n",
    "print(e1)\n",
    "print('-'*40)\n",
    "\n",
    "e2 = torch.rand(5,3)\n",
    "print(e2)\n",
    "print('-'*40)\n",
    "\n",
    "e3 = torch.zeros(5, 3, dtype=torch.long) # 全0\n",
    "print(e3)\n",
    "print('-'*40)\n",
    "\n",
    "e4 = torch.tensor([5.5, 12, -9])\n",
    "print(e4)"
   ],
   "execution_count": 4,
   "outputs": []
  },
  {
   "cell_type": "code",
   "id": "48868a6f09333986",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-12-21T14:36:52.732703Z",
     "start_time": "2024-12-21T14:36:52.723890Z"
    }
   },
   "source": [
    "x1 = torch.ones(5,3)\n",
    "print(x1)\n",
    "# 根据现有的tensor来创建：\n",
    "x2 = x1.new_ones(3,4) # 不指定数据类型，新的tensor和旧的tensor类型一致\n",
    "print(x2)\n",
    "x22 = x1.new_zeros(3,5)\n",
    "print(x22)\n",
    "\n",
    "x3 = torch.randn_like(x1 ,dtype=torch.float16) # 数据尺寸不变，类型变化\n",
    "print(x3)"
   ],
   "execution_count": 5,
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "af6035b9",
   "metadata": {},
   "source": [
    "print(x1.size())\n",
    "print(x1.shape)\n",
    "# 返回完全一样，一个是方法调用，一个是属性，返回值就是一个tuple，支持所有tuple的操作"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "67539be1",
   "metadata": {},
   "source": [
    "x3 = torch.randn(4,3) # 均匀分布\n",
    "print(x3)\n",
    "\n",
    "x4 = torch.randperm(5) # 随机排列\n",
    "print(x4)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "484f6b1b",
   "metadata": {},
   "source": [
    "# 算术操作\n",
    "x = torch.rand(4,3)\n",
    "y = torch.rand_like(x)\n",
    "print(x,'\\n', y)\n",
    "print('-'*40)\n",
    "print(x+y)\n",
    "print('-'*40)\n",
    "print(torch.add(x,y))\n",
    "print('-'*40)\n",
    "\n",
    "z = torch.empty_like(x)\n",
    "torch.add(x,y,out=z)\n",
    "print(z)\n",
    "print('-'*40)\n",
    "\n",
    "y.add_(x) #这种是inplace的\n",
    "print(y)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "a28ad5ee",
   "metadata": {},
   "source": [
    "# 索引\n",
    "y = x[0, :]\n",
    "\n",
    "y+=1\n",
    "print(y)\n",
    "print(x[0, :]) # 索引出来的部分和原部分共享内存，同步修改"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "de7a3d1a",
   "metadata": {},
   "source": [
    "print(x)\n",
    "print(torch.nonzero(x)) # 罗列所有非0的数据，和源数据的shape不同\n",
    "\n",
    "z = torch.zeros(1,2)\n",
    "print(z)\n",
    "torch.index_select(x, 1, z)\n",
    "# help(torch.index_select)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "c4bcd7a7",
   "metadata": {},
   "source": [
    "# 改变形状： x.view()\n",
    "x = torch.randn(5,3)\n",
    "print(x)\n",
    "\n",
    "y = x.view(3,-1) # -1表示-1所在的维度由其他维度推算出来\n",
    "x[0][1] = 100\n",
    "print(y.shape)\n",
    "print(x)\n",
    "print(y)\n",
    "# 注意view()返回的tensor和原来那个共享内存，view只是仅仅改了tensor的“视图”"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "c6d9e47b",
   "metadata": {},
   "source": [
    "# 如果想返回一个新的副本，同时改变形状，可以用clone (有reshape但是它也不靠谱，并不能保证返回的是新副本)\n",
    "x = torch.randn(5,3)\n",
    "print(x)\n",
    "\n",
    "y = x.clone().view(3,-1) # -1表示-1所在的维度由其他维度推算出来\n",
    "x[0][1] = 100\n",
    "print(y.shape)\n",
    "print(x)\n",
    "print(y) # y[0][1]的值不会跟着发生改变\n",
    "\n",
    "# 使用clone还有一个好处是会被记录在计算图中，即梯度传回副本时，也会被传到源tensor"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "10c2e4bd",
   "metadata": {},
   "source": [
    "x = torch.randn(1)\n",
    "print(x)\n",
    "print(x.item()) # item():将一个标量tensor转换为python的number"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f295d17c",
   "metadata": {},
   "source": [
    "# 线性代数：\n",
    "# trace：对角线元素之和（迹）\n",
    "# diag: 对角线元素\n",
    "# triu/tril: 矩阵的上三角、下三角\n",
    "# mm/bmm: 矩阵的乘法,batch的矩阵乘法\n",
    "# addmm/addbmm/addmv/addr/badbmm..: 矩阵运算\n",
    "# t: 转置\n",
    "# dot/cross: 内积/外积\n",
    "# inverse: 求逆矩阵\n",
    "# svd: 奇异值分解"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "f5062b86",
   "metadata": {
    "scrolled": true
   },
   "source": [
    "# 广播机制(似乎只有在一个维度为1的时候才生效)\n",
    "x = torch.arange(1,7).view(1,-1)\n",
    "print(x.shape)\n",
    "print(x)\n",
    "print('-'*40)\n",
    "y = torch.arange(1,4).view(3,1)\n",
    "print(y.shape)\n",
    "print(y)\n",
    "print(x*y)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "75ab273c",
   "metadata": {},
   "source": [
    "# 索引、view操作是不会新开内存的，但y=y+x这种操作是会新开的\n",
    "x = torch.arange(1,4)\n",
    "y = torch.arange(1,4)\n",
    "id1 = id(y)\n",
    "\n",
    "y = y+x\n",
    "print(id(y) == id1) # false"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "254976fa",
   "metadata": {},
   "source": [
    "x = torch.arange(1,4)\n",
    "y = torch.arange(1,4)\n",
    "id1 = id(y)\n",
    "\n",
    "# y[:] = y+x\n",
    "# torch.add(x,y, out=y)\n",
    "# y+=x\n",
    "y.add_(x)\n",
    "print(id(y) == id1) # true\n",
    "# 也可以在add函数中指定out的值，或者用自加运算符达到上述效果+=或者add_()\n",
    "# 即：torch.add(x,y, out=y)   y+=x    y.add_(x)\n",
    "# 这四种操作效果一致"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "id": "6cafa2a9",
   "metadata": {},
   "source": [
    "# tensor和numpy相互转换\n",
    "# 很容易用numpy()和from_numpy()来进行转换，它们产生的tensor会和之前的共享内存，速度快\n",
    "# torch.tensor()会对数据进行拷贝，不共享内存\n",
    "a = torch.ones(4)\n",
    "b = a.numpy()\n",
    "print(a, b)\n",
    "a += 1\n",
    "print(a, b)\n",
    "b += 1\n",
    "print(a, b)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "3b6b6263",
   "metadata": {},
   "source": [
    "ava = torch.cuda.is_available()\n",
    "print(ava)\n",
    "x = torch.ones(4)\n",
    "print(x)\n",
    "x = x.to('cuda')\n",
    "print(x)"
   ],
   "outputs": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
